<?php
require_once 'OAuth/OAuthException.php';
require_once 'OAuth/OAuthServer.php';

/**
 * Class RestController
 *
 * Description for class OAuth controller
 *
 * @author: Phong Linh <langxangvn@gmail.com>
*/
class ApiOAuthController extends Zend_Controller_Action {
	/**
	 * This is method init
	 *
	 * @return mixed This is the return value description
	 *
	 */
	public function init() {
		/* Initialize action controller here */
	}
	
	/**
	 * indexAction
	 *
	 * @return void
	 */
	public function indexAction() {		
		$this->view->title = "Welcome to REST API web services";
		$this->view->headTitle($this->view->title);
		
		// get the user info from the storage (session)  
		$storage = Zend_Auth::getInstance()->getStorage();	// storage of Zend_Auth
		$user = $storage->read();
		$this->view->user = $user;
	}
	
	/**
	 * This is method loginAction
	 *
	 * @return void
	 *
	 */
	public function loginAction() 
	{		
		if(Zend_Auth::getInstance()->hasIdentity()) {	// already logged in			
			$this->_forward('authorize');				// forward to authorize
		} else {										// do login for authorize
			// make sure URL always is /api/oauth/authorize, only authorize call login action
			if($this->getRequest()->getPathInfo() != '/api/oauth/authorize') {
				$this->_helper->redirector('index');		// maybe error redirect to index
			}
			
			$server = new OAuthServer();	// initialize API request
			$oauthToken = $server->getParam(OAuthRequest::$OAUTH_TOKEN);
			
			if(empty($oauthToken)) {	// missing oauth_token
				$this->_helper->redirector('index');		// maybe error redirect to index
			}
			
			$this->view->title = "Please login to use REST API web services";
			$this->view->headTitle($this->view->title);
			
			$form = new Form_Login();
			// set action is authorize, if not authenticated authorize will re-forward to login
			$form->setAction('./authorize?' . OAuthRequest::$OAUTH_TOKEN . '=' . $oauthToken)
				->setMethod('POST');
			
			if ($this->getRequest()->isPost()) {
				$data = $this->_request->getPost();		
				if ($form->isValid($data)) {			
					$user = new Model_DbTable_Users();				
					$email = $form->getValue('auth_email');
					$password = $form->getValue('auth_password');
										
					if (true === $message = $user->login($email, $password)) {		// try login
						$this->_forward('authorize');
					} else {						
						$this->view->errors = $message;	// set errors
					}
				} else {
					$form->populate($data);					
				}
			}
			
			$this->view->form = $form;
		}
	}		

	/**
	 * This is method logoutAction
	 *
	 * @return void
	 *
	 */
	public function logoutAction()
	{
		// shutdown view script and layout
		$this->_helper->viewRenderer->setNoRender(true);
		Zend_Layout::getMvcInstance()->disableLayout();
		
		$auth = Zend_Auth::getInstance();	
		// delete the information from the session
		$auth->clearIdentity();		
		Zend_Session::forgetMe();
		
		// redirect to home
		$this->_helper->redirector('index', 'index');	// redirect to home
	}
		
	/**
	 * indexAction
	 *
	 * @return void
	 */
	public function requestTokenAction() {
		$this->handle('requestToken');
	}
	
	/**
	 * indexAction
	 *
	 * @return void
	 */
	public function authorizeAction() {	
		if(!Zend_Auth::getInstance()->hasIdentity()) {		// not logged in
			$this->_forward('login');	// forward to login
		} else {
			// make sure URL always is /api/oauth/authorize, only authorize call login action
			if($this->getRequest()->getPathInfo() != '/api/oauth/authorize') {
				$this->_helper->redirector('index');		// maybe error redirect to index
			}
			
			$server = new OAuthServer();	// initialize API request
			$oauthToken = $server->getParam(OAuthRequest::$OAUTH_TOKEN);
			
			if(empty($oauthToken)) {	// missing oauth_token
				$this->_helper->redirector('index');		// maybe error redirect to index
			}
			
			$this->view->title = "Please authorize to use REST API web services";
			$this->view->headTitle($this->view->title);
			
			$form = new Form_Authorize();
			$form->setAction('./authorize?' . OAuthRequest::$OAUTH_TOKEN . '=' . $oauthToken)
				->setMethod('POST');
			
			// check if forward from login
			$fromLogin = $this->getRequest()->getParam('auth_login');			
			
			if ($this->getRequest()->isPost() && $fromLogin !== 'Login') 
			{
				$data = $this->_request->getPost();		
				if($data['commit']) {				
					$authorized = true;
				} else {
					$authorized = false;
				}
				
				try {
					// Get the user info from the storage (session)  
					$storage = Zend_Auth::getInstance()->getStorage();	// storage of Zend_Auth
					$user = $storage->read();
					
					// if not redirect oob here
					$this->view->form = false;
					$this->view->user = $user;
					
					if($authorized) {
						$server->authorizeVerify();
						$verifier = $server->authorizeFinish($authorized, $user->id);
						
						$this->view->verifier = $verifier;
						$this->view->authorized = true;
					} else {
						$this->view->authorized = false;
					}
				} catch(Exception $e) {	
					$this->view->message = $e->getMessage();
				}
			} else {			
				$this->view->form = $form;
			}
		}	
	}
	
	/**
	 * indexAction
	 *
	 * @return void
	 */
	public function accessTokenAction() {
		$this->handle('accessToken');
	}
	
	/**
	 * *
	 *
	 * @param mixed $action This is a description
	 * @return mixed This is the return value description
	 *
	 */	
	protected function handle($action) {
		$this->_helper->Layout->disableLayout();		// disble layout
		$this->_helper->ViewRenderer->setNoRender();	// no renderer
		
		$params = $this->_request->getParams();
		unset($params['controller']);
		unset($params['action']);
		unset($params['module']);
		
		if (!array_key_exists(OAuthRequest::$API_FORMAT, $params)){
			$format = 'json';
		} else {
			$format = $params[OAuthRequest::$API_FORMAT];
		}
		
		switch ($format) {
			case 'xml':;
				$this->_response->setHeader('Content-Type', 'text/xml');
				break;
			
			case 'plain-text':				
				$this->_response->setHeader('Content-Type', 'text/html');
				break;
			
			case 'json':			
				$this->_response->setHeader('Content-Type', 'application/json');
				break;
			
			default:
				$this->_response->setHeader('Content-Type', 'application/json');
		}	
		
		try {
			$server = new OAuthServer();
			
			$result = false;
			if($action === 'accessToken') {
				$isSSL = isset($_SERVER['HTTPS']);	// check if is SSL or not
				$xauthMode = $server->getParam(OAuthRequest::$X_AUTH_MODE);
				$xauthPassword = $server->getParam(OAuthRequest::$X_AUTH_PASSWORD);
				$xauthUsername = $server->getParam(OAuthRequest::$X_AUTH_USERNAME);	
				$isXAuth = !(empty($xauthUsername) || empty($xauthPassword)) && 
					($xauthMode === "client_auth");				
				
				if($isXAuth) {
					$result = $server->handle('clientAuth');
				} else {
					$result = $server->handle('accessToken');
				}
			} else {
				$result = $server->handle($action);
			}
			
			switch ($format) {
				case 'xml':
					$response = OAuthResponse::generate(array('result' => $result), true, false);
					break;
				
				case 'plain-text':				
					$response = OAuthResponse::plain($result);
					break;
				
				case 'json':
					$response = Zend_Json::encode($result);	
					break;
				
				default:
					$format = 'json';
					$code = OAuthRequestVerifier::$UNSUPPORTED_RESPONSE_FORMAT;
					$error = $server->getErrorMessage($code);
					throw new OAuthException($error, $code);
			}			
			
			$this->_response->setBody($response);
		} catch(OAuthException $e) {
			$error = $server->fault($e, $format);
			$this->_response->setBody($error);
		} catch(Exception $e) {
			$error = $server->fault($e, $format);
			$this->_response->setBody($error);
			//$this->_response->setRawHeader('HTTP/1.0 400 Bad Request');		
		}
	}
}
?>